/* Copyright (c) 2002-2020 by Kithara Software GmbH. All rights reserved. */

//##############################################################################################################
//
// File:        _KitharaSmp.cpp
//
// Description: Definition of convenience functions used by the samples
//
// Creator:     a.lun 2002-12-18
//
//##############################################################################################################

   /*=====================================================================*\
   |                    *** DISCLAIMER OF WARRANTY ***                     |
   |                                                                       |
   |       THIS  CODE AND INFORMATION IS PROVIDED "AS IS"  WITHOUT         |
   |       A  WARRANTY OF  ANY KIND, EITHER  EXPRESSED OR  IMPLIED,        |
   |       INCLUDING  BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF         |
   |       MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.        |
   \*=====================================================================*/

//##############################################################################################################
//
// Purpose:
// The functions defined in this file are convenience functions used by the samples.
// They provide an input/output layer, abstracting the different supported programming languages and
// environments.
//
//##############################################################################################################


//--------------------------------------------------------------------------------------------------------------
// _KitharaSmp
//--------------------------------------------------------------------------------------------------------------

#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif

#define NO_STRICT
#define WIN32_LEAN_AND_MEAN

#pragma pack(push, 8)
#include <windows.h>
#include <stdarg.h>
#pragma pack(pop)

#include "_KitharaSmp.h"

//------ outputTxt ------
void outputTxt(const char* pText, bool line) {
  if (pText && *pText)
    printf("%s%s", pText, line ? "\n" : "");
  else
    printf(line ? "\n" : "");
}

//------ outputBool ------
void outputBool(int value, const char* pPreText, const char* pPostText, bool line) {
  printf("%s%s%s%s", pPreText ? pPreText : "", value ? "true" : "false" , pPostText ? pPostText : "",
    line ? "\n" : "");
}

//------ outputDec ------
void outputDec(int64 value, const char* pPreText, const char* pPostText, bool line) {
#ifdef _MSC_VER
  printf("%s%I64d%s%s", pPreText ? pPreText : "", value, pPostText ? pPostText : "", line ? "\n" : "");
#else
  printf("%s%lld%s%s", pPreText ? pPreText : "", value, pPostText ? pPostText : "", line ? "\n" : "");
#endif
}

//------ outputFloat ------
void outputFloat(double value, const char* pPreText, const char* pPostText, bool line) {
  printf("%s%5.2lf%s%s", pPreText ? pPreText : "", value, pPostText ? pPostText : "", line ? "\n" : "");
}

//------ outputHex02 ------
void outputHex02(byte value, const char* pPreText, const char* pPostText, bool line) {
  printf("%s%02X%s%s", pPreText ? pPreText : "", value, pPostText ? pPostText : "", line ? "\n" : "");
}

//------ outputHex04 ------
void outputHex04(ushort value, const char* pPreText, const char* pPostText, bool line) {
  printf("%s%04X%s%s", pPreText ? pPreText : "", value, pPostText ? pPostText : "", line ? "\n" : "");
}

//------ outputHex08 ------
void outputHex08(uint value, const char* pPreText, const char* pPostText, bool line) {
  printf("%s%08X%s%s", pPreText ? pPreText : "", value, pPostText ? pPostText : "", line ? "\n" : "");
}

//------ outputHex16 ------
void outputHex16(uint64 value, const char* pPreText, const char* pPostText, bool line) {
#ifdef _MSC_VER
  printf("%s%016I64X%s%s", pPreText ? pPreText : "", value, pPostText ? pPostText : "", line ? "\n" : "");
#else
  printf("%s%016llX%s%s", pPreText ? pPreText : "", value, pPostText ? pPostText : "", line ? "\n" : "");
#endif
}

//------ outputIpv4 ------
void outputIpv4(uint ip, const char* pPreText, const char* pPostText, bool line) {
  printf("%s%d.%d.%d.%d%s%s", pPreText ? pPreText : "", ip >> 24 & 0xFF, ip >> 16 & 0xFF,
    ip >>  8 & 0xFF, ip >>  0 & 0xFF, pPostText ? pPostText : "", line ? "\n" : "");
}

//------ outputErr ------
void outputErr(KSError error, const char* pFuncName, const char* pComment) {
  if (error == KS_OK)
    return;

  HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
  CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
  GetConsoleScreenBufferInfo(hConsole, &consoleInfo);

  SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
  const char* pError;
  KS_getErrorString(error, &pError, KSLNG_DEFAULT);
  printf("ERROR (%08X = \'%s\') -\n  %s: %s\n", error, pError, pFuncName, pComment);

  SetConsoleTextAttribute(hConsole, consoleInfo.wAttributes);
  if (KS_getErrorDescription(error, pFuncName, &pError, KSLNG_DEFAULT) == KS_OK)
    outputTxt(pError);
}
#define KSMP_INPUTBUFFERSIZE 256
//------ inputTxt ------
char* inputTxt(const char* pPreText, const char* pDefault) {
  printf("%s", pPreText);
  if (pDefault && *pDefault)
    printf("[%s] ", pDefault);
  static char _pBuffer[KSMP_INPUTBUFFERSIZE];
  for (int i = 0;;) {
    int ch = myGetch();
    if (isprint(ch))
      myPutch(ch);
    if (ch == '\b') {
      if (i > 0) {
        --i;
        printf("\b \b");
      }
      continue;
    }
    if (ch == '\r' || i == KSMP_INPUTBUFFERSIZE - 1) {
      printf("\n");
      if (i == 0)
        strcpy(_pBuffer, pDefault);
      else
        _pBuffer[i] = '\0';
      break;
    }
    if (isprint(ch))
      _pBuffer[i++] = ch;
  }
  return _pBuffer;
}
#undef KSMP_INPUTBUFFERSIZE

//------ inputDec ------
int inputDec(const char* pPreText, const char* pDefault) {
  int dec = 0;
  sscanf(inputTxt(pPreText, pDefault), "%d", &dec);
  return dec;
}

//------ inputDec ------
int inputDec(const char* pPreText, int defaultVal) {
  char pBuf[32];
  sprintf(pBuf, "%d", defaultVal);
  return inputDec(pPreText, pBuf);
}

//------ inputDec64 ------
int64 inputDec64(const char* pPreText, const char* pDefault) {
  int64 dec = 0;
#ifdef _MSC_VER
  const char formatString[] = "%I64d";
#else
  const char formatString[] = "%lld";
#endif
  sscanf(inputTxt(pPreText, pDefault), formatString, &dec);
  return dec;
}

//------ inputDec64 ------
int64 inputDec64(const char* pPreText, int64 defaultVal) {
  char pBuf[32];
#ifdef _MSC_VER
  const char formatString[] = "%I64d";
#else
  const char formatString[] = "%lld";
#endif
  sprintf(pBuf, formatString, defaultVal);
  return inputDec64(pPreText, pBuf);
}

//------ inputHex ------
int inputHex(const char* pPreText, const char* pDefault) {
  int hex = 0;
  sscanf(inputTxt(pPreText, pDefault), "%x", &hex);
  return hex;
}

//------ inputHex ------
int inputHex(const char* pPreText, int defaultVal) {
  char pBuf[32];
  sprintf(pBuf, "%x", defaultVal);
  return inputHex(pPreText, pBuf);
}

//------ waitTime ------
void waitTime(uint time) {
  int delay = time / 10000;
  Sleep(delay);
}